package hivMultiCompartment;

import java.util.Iterator;

public class OrganNonSpatial extends OrganGeneral {
	
	//virtual ports to conduct export
	public PortExit exitToLN;
	public PortExit exitToThymus;
	public int lymphNodeVirusCount;
	public double probNeutralizing;
	/**
	 * constructor: 
	 * reference to model;
	 * build cell list, virus list and input queue for cells and virus;
	 * @param aModel
	 */
	public OrganNonSpatial ( Model aModel) {
		super(aModel);
		lymphNodeVirusCount = 0;
		probNeutralizing = 0;
		exitToLN = new PortExit(null, aModel.lymphNode);
		exitToThymus = new PortExit(null, aModel.thymus);
		exitToLN.resetOrgan(this);
		exitToThymus.resetOrgan(this);
	}
	
	public void step (){
		
		//add agents in input queue to cell/virus list
		recruitAgents();
		
		//update neutralization probability
		calculateNeutralizationProb();
		
		//shuffle agents
		shuffleAgents();
		Iterator<Cell> cIter = cellList.iterator();
		while (cIter.hasNext()) {
			Cell c = cIter.next();
			boolean toRemove = c.step();
			if(toRemove) {
				cIter.remove();
			}
		}
		cellList.addAll(prolifCellList);
		prolifCellList.clear();
		Iterator<Virus> vIter = virusList.iterator();
		while (vIter.hasNext()) {
			Virus v = vIter.next();
			boolean toRemove = v.step();
			if(toRemove) {
				vIter.remove();
				//System.out.printf("Exit event! virus left: %d; Blood input queue size: %d\n", virusList.size(), theModel.bloodStream.inputVirusList.size());
			}
		}	
		
		// Interactions between agents
		//cells interact
		cIter = cellList.iterator();
		while (cIter.hasNext()) {
			Cell c = cIter.next();
			if (c.isAlive()){
				c.statesAndInteractions();
			}
		}
		//virus interact
		vIter = virusList.iterator();
		while (vIter.hasNext()) {
			Virus v = vIter.next();
			if (v.isAlive()){
				v.statesAndInteractions();
			}
		}
				
		removeDeadAgents();
	}
	
	public void recruitAgents(){
		processInputQueues();
	}
	
	public void processInputQueues() {
		//cell recruitment queue
		Iterator<Cell> cIter = recruitCellList.iterator();
		while (cIter.hasNext()) {
			Cell c = cIter.next();
			c.updateMyList(cellList);
		}
		cellList.addAll(recruitCellList);
		recruitCellList.clear();
		
		//cell input queue
		cIter = inputCellsList.iterator();
		while (cIter.hasNext()) {
			Cell c = cIter.next();
			c.updateMyList(cellList);
		}
		cellList.addAll(inputCellsList);
		inputCellsList.clear();
		
		//virus input queue	
		Iterator<Virus> vIter = inputVirusList.iterator();
		while (vIter.hasNext()) {
			Virus v = vIter.next();
			v.updateMyList(virusList);
		}
		virusList.addAll(inputVirusList);
		inputVirusList.clear();
	}
	
	private void calculateNeutralizationProb(){
		double cAb = theModel.lymphNode.getTotalAntibodyLoad();
		lymphNodeVirusCount = virusList.size();
		int cVirus = lymphNodeVirusCount;
		double ratioAbVirus = cAb / cVirus;
		double productAbVirus = cAb*cVirus;
		probNeutralizing = 2*Math.sqrt(ratioAbVirus)/(ratioAbVirus + GlobalConstants.antibodyEfficiency);
		probNeutralizing *= productAbVirus * (productAbVirus + GlobalConstants.antibodyVirusHalfMaxProductBlood);
	}
}
